package wangwenjun.phase3.util;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import util.ThreadUtil;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * @author ChangLiang
 * @date 2020/6/27
 */
@Slf4j
public class FairUnFairLockTest {

    @Test
    @DisplayName("test fair lock")
    public void test() throws InterruptedException {
        PrintQueue printQueue = new PrintQueue(true);
        IntStream.range(0,10).forEach(i->new Thread(()->printQueue.printJob(),"my-thread-"+i).start());
        Thread.currentThread().join();
    }

    @Test
    @DisplayName("test unfair lock")
    public void test2() throws InterruptedException {
        PrintQueue printQueue = new PrintQueue(false);
        IntStream.range(0,10).forEach(i->new Thread(()->printQueue.printJob(),"my-thread-"+i).start());
        Thread.currentThread().join();
    }

    class PrintQueue {

        private Lock queueLock;

        public PrintQueue(boolean isFair) {
            queueLock = new ReentrantLock(isFair);
        }

        public void printJob() {

            // 模拟打印第一次
            queueLock.lock();
            try {
                int consumptionTime = ThreadLocalRandom.current().nextInt(1, 5);
                log.info("正在进行第一次打印，需要 {} 秒", consumptionTime);
                ThreadUtil.sleepForSeconds(consumptionTime);
            } finally {
                queueLock.unlock();
            }

            // 模拟打印第二次
            queueLock.lock();
            try {
                int consumptionTime = ThreadLocalRandom.current().nextInt(1, 5);
                log.info("正在进行第二次打印，需要 {} 秒", consumptionTime);
                ThreadUtil.sleepForSeconds(consumptionTime);
            } finally {
                queueLock.unlock();
            }
        }
    }

}
